# -*- coding: utf-8 -*-
"""
常用函数
train()：训练线性模型
predict()：对testing数据做预测
svm_read_problem()：读取libsvm格式的数据
load_model()：load模型
save_model()：将模型存储为文件
evaluations()：评价预测结果

model = train(y, x[, 'training_options'])
# y是list/tuple类型，长度为l的训练标签向量
# x是list/tuple类型的训练实例，list中的每一个元素是list/tuple/dictory类型的feature向量
#以下写法的作用是相同的
model = train(prob[, 'training_options'])
model = train(prob, param)

# examples
y, x = svm_read_problem('../heart_scale')
# 读入libsvm格式的数据
prob = problem(y, x)
# 将y,x写作prob
param = parameter('-s 3 -c 5 -q')
# 将参数命令写作param

m = train(y, x, '-c 5')
m = train(prob, '-w1 5 -c 5')
m = train(prob, param)
# 进行训练

CV_ACC = train(y, x, '-v 3')
# -v 3 是指进行3-fold的交叉验证
# 返回的是交叉验证的准确率

best_C, best_rate = train(y, x, '-C -s 0')

p_labs, p_acc, p_vals = predict(y, x, m [,'predicting_options'])
# y是testing data的真实标签，用于计算准确率
# x是待预测样本
# p_labs: 预测出来的标签
# p_acc: tuple类型，包括准确率，MSE，Squared correlation coefficient(平方相关系数)
# p_vals: list, 直接由模型计算出来的值，没有转化成1，0的值，也可以看做是概率估计值

(ACC, MSE, SCC) = evaluations(ty, pv)
# ty: list, 真实值
# pv: list, 估计值


"""


from liblinear import *
import preprocess.bag as bag
import preprocess.CleanUp as CleanUp

class SVM:

    classif=None

    def __init__(self):
        pass


    def train1(self,features,labels):

        prob = problem(labels, features)
        param = parameter('-s 1 -q')
        self.classif = train(prob, param)
        pass

    def train(self,features,labels):

        prob = problem(labels, features)
        param = parameter('-s 2 -C')
        bestC,rate = train(prob, param)
        print("Best C: %d rate: %d"%(bestC,rate))
        param = parameter('-s 2 -q -c ' + str(bestC))
        self.classif = train(prob, param)
        pass


    def validation(self,features,labels):
        p_labs, p_acc, p_vals = predict(labels,features,self.classif)
        return p_acc[0]/100

    def predict(self,features):
        p_labs, p_acc, p_vals = predict([],features,self.classif)
        return p_labs

    def cross_validation(self,features,labels,nfold=5):
        prob = problem(labels,features)
        param = parameter('-s 0 -C -q -v '+ str(nfold))
        self.classif = train(prob, param)
        return ""

    def load(self,filename):
        self.classif = load_model(filename)
        pass


    def save(self,filename):
        save_model(filename,self.classif)
        pass

    @staticmethod
    def convert_to_data_as_liblinear_input_of_terminal(features,labels,filename,feature_dict=[], label_dict=[]):

        X_SparseData = bag.FeatureList2SVMSparseData(features, feature_dict)

        X, Y = CleanUp.remove_item_if_feature_empty(X_SparseData, labels)

        Y_index = bag.Label2Index(Y,label_dict)

        f = open(filename, "a+")

        for x, y in zip(X, Y_index):

            feature_line = ""
            keys = sorted(x.keys())
            for one in keys:
                feature_line += (str(one) + ":" + str(x[one]) + " ")
            f.write(str(y) + " " + feature_line + "\n")
        f.close()

if __name__ == '__main__':

    _feature_dict = ['a','c']

    features = [
        ['a','b'],
        ['b','c'],
        ['a']
    ]

    labels = [
        1,
        2,
        1
    ]

    classif = SVM()
    classif.train(features,labels)
    print(classif.validation(features,labels))
    print(classif.cross_validation(features,labels,5))

    pass